﻿using System;
using System.Collections.Generic;
using HighDiveEngine.Model;
using HighDiveEngine.Resources;

namespace HighDiveEngine.Aggregates
{
    /// <summary>
    /// Comparer Class used to sort a DiveList.
    /// Send an instance of this class as an attribute to the DiveList.Sort method.
    /// </summary>
    public class DiveListComparer : IComparer<Dive>
    {
        private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        #region Properties

        private DiveListSortType _sortOnAttribute;
        private bool _descendingSort;

        #endregion

        #region Constructors

        /// <summary>
        /// Default sort on QueueOrderNumber
        /// </summary>
        /// <param name="descendingSort">Specifies whether to sort descending or ascending</param>
        public DiveListComparer(bool descendingSort = true)
        {
            _sortOnAttribute = DiveListSortType.QueueOrderNumber;
            _descendingSort = descendingSort;
            if (Log.IsInfoEnabled)
            {
                Log.Info("Sorting DiveList, SortType == " + _sortOnAttribute + ", desc == " + _descendingSort);
            }
        }

        /// <summary>
        /// Sort on a specific attribute
        /// </summary>
        /// <param name="sortType">The attribute to sort on</param>
        /// <param name="descendingSort">Specifies whether to sort descending or ascending</param>
        public DiveListComparer(DiveListSortType sortType, bool descendingSort = true)
        {
            _sortOnAttribute = sortType;
            _descendingSort = descendingSort;
            if (Log.IsInfoEnabled)
            {
                Log.Info("Sorting DiveList, SortType == " + _sortOnAttribute + ", desc == " + _descendingSort);
            }
        }

        #endregion

        #region Private Methods

        private int CompareTotalScore(Dive x, Dive y)
        {
            if (_descendingSort)
            {
                if (x.TotalScore > y.TotalScore)
                {
                    return 1;
                }
                if (x.TotalScore == y.TotalScore)
                {
                    return 0;
                }
                return -1;
            }
            else
            {
                if (x.TotalScore < y.TotalScore)
                {
                    return 1;
                }
                if (x.TotalScore == y.TotalScore)
                {
                    return 0;
                }
                return -1;
            }
        }

        private int CompareQueueOrderNumber(Dive x, Dive y)
        {
            if (_descendingSort)
            {
                if (x.QueueOrderNumber > y.QueueOrderNumber)
                {
                    return 1;
                }
                if (x.QueueOrderNumber == y.QueueOrderNumber)
                {
                    return 0;
                }
                return -1;
            }
            else
            {
                if (x.QueueOrderNumber < y.QueueOrderNumber)
                {
                    return 1;
                }
                if (x.QueueOrderNumber == y.QueueOrderNumber)
                {
                    return 0;
                }
                return -1;
            }
        }

        /// <summary>
        /// Compares diver names.
        /// If first names are equal it will compare last names.
        /// If first and last names are equal it will compare Queue Order
        /// </summary>
        private int CompareDiverName(Dive x, Dive y)
        {
            int comparisonResult = String.Compare(x.Diver.FirstName, y.Diver.FirstName, StringComparison.Ordinal);
            if (comparisonResult == 0)
            {                
                comparisonResult = String.Compare(x.Diver.LastName, y.Diver.LastName, StringComparison.Ordinal);
                if (comparisonResult == 0)
                {
                    return CompareQueueOrderNumber(x, y);
                }
            }
            if (_descendingSort)
            {
                return comparisonResult;
            }
            return -comparisonResult;
        }

        #endregion

        #region IComparer

        public int Compare(Dive x, Dive y)
        {
            if (Log.IsDebugEnabled)
            {
                Log.Debug("Comparing Dives With DbId: (" + x.DbId + ", " + y.DbId + ") SortType == " + _sortOnAttribute + ", desc == " + _descendingSort); 
            }
            switch (_sortOnAttribute)
            {
                case DiveListSortType.DiverName:
                    return CompareDiverName(x, y);
                case DiveListSortType.QueueOrderNumber:
                    return CompareQueueOrderNumber(x, y);
                case DiveListSortType.TotalScore:
                    return CompareTotalScore(x, y);
                default:
                    return 0;
            }
        }

        #endregion
    }
}
